/**
 * @file uart.c
 * @author LuoJing
 * @version 1.0
 * @date 2018-09-14
 * @brief YC uart api
 * @details Includes uart initialization, reading and writing uart, sending events, and printing logs
 */

 
#include "uart.h"
#include "util.h"

#if 1 //YC_PERIPHERAL_UART

  void UART_Init(UartInitRegDef *Def_struct)
{
#define UARTC_BIT_ENABLE 	(1<<0)
#define BAUD_USE_SETTING	(1<<7)
#define SEL_UART_GPIO		(1<<2)
#define TURN_ON_UART_CLOCK (1<<7)	
#define UART_CLK_SEL_DPLL	(1<<0)

	REG8(ADDR_REG_UART_CTRL) = 0;	//Disable uart

	REG8(ADDR_REG_GPIO_SEL1) |= SEL_UART_GPIO;
	REG8(ADDR_REG_GPIO_PU0) |= 0x80;
	REG8(ADDR_REG_CONFIG) |= UART_CLK_SEL_DPLL;
 	
	REG16(ADDR_REG_UART_BAUD) =  Def_struct->USART_BaudRate;
	
	REG16(ADDR_REG_UART_RSADDR) = REG16(ADDR_REG_UART_RRPTR)=Def_struct->USART_RXaddr;
	
	REG16(ADDR_REG_UART_READDR) = Def_struct->USART_RXaddr + Def_struct->USART_RXLen;
	
	REG16(ADDR_REG_UART_TSADDR) = REG16(ADDR_REG_UART_TWPTR) = \
	REG16(ADDR_REG_UART_TRPTRP) = Def_struct->USART_TXaddr;
	
	REG16(ADDR_REG_UART_TEADDR) = Def_struct->USART_TXaddr + Def_struct->USART_TXLen;

	REG8(ADDR_REG_CLK0FF+1) &= (~TURN_ON_UART_CLOCK);			//open uart clk

	REG8(ADDR_REG_UART_CTRL) = Def_struct->USART_HardwareFlowControl |Def_struct->USART_Mode |\
								Def_struct->USART_Parity |Def_struct->USART_StopBits |\
								Def_struct->USART_WordLength |UARTC_BIT_ENABLE |BAUD_USE_SETTING;

	return;
}

 u16_t UART_ReciveData(u8_t* pbuff, u16_t len)
{
	u16_t i = 0;
	u8_t* rrptr = (u8_t *)REG16(ADDR_REG_UART_RRPTR);

	if(0 == REG16(ADDR_REG_UART_RXITEMS))
	{
		return 0;
	}
	for(i=0;i<len;i++)
	{
		xmemcpy(pbuff++, rrptr++, 1);

		if((u16_t)rrptr == REG16(ADDR_REG_UART_READDR) + 1)		//rrptr reach the end of buffer
		{
			rrptr = (u8_t *)REG16(ADDR_REG_UART_RSADDR);
		}
		if((u16_t)rrptr == REG16(ADDR_REG_UART_RWPTR) )	//read all data already
		{
			REG16_WRITE(ADDR_REG_UART_RRPTR,(u16_t)rrptr);
			return (i+1);
		}
	}
	REG16_WRITE(ADDR_REG_UART_RRPTR,(u16_t)rrptr);
	return i;
}

 void UART_SendData(u8_t* pbuff, u16_t len)
{
	int i;
	u8_t *twptr = (u8_t *)REG16(ADDR_REG_UART_TWPTR);
	u16_t tx_items = REG16(ADDR_REG_UART_TXITEMS);
	u16_t tx_end = REG16(ADDR_REG_UART_TEADDR); 
	u16_t tx_start = REG16(ADDR_REG_UART_TSADDR); 

	YC_ASSERT(tx_items + len <= tx_end - tx_start);
	
	for(i=0;i<len;i++)
	{
		xmemcpy(twptr++, pbuff++, 1);
		if(((short)twptr-1) == tx_end)	//twptr reach the end of buffer
		{
			REG16_WRITE(ADDR_REG_UART_TWPTR,tx_end);
			twptr = (u8_t *)tx_start;	//reset twptr
		}	
	}	
	REG16_WRITE(ADDR_REG_UART_TWPTR,(u16_t)twptr);
	return;
}

void Uart_SendEvent(u8_t* EventType)
{
	u8_t DataBuff[16];
	if(*EventType == EVEVT_START_CONNECT) {
		BT_AdvEnable(FALSE);
		DataBuff[0] = 0xAA;
		DataBuff[1] = 0x01;
		UART_SendData(DataBuff,2);
	}
	else if(*EventType == EVENT_DISCONNECT) {
		BT_AdvEnable(TRUE);
		DataBuff[0] = 0xAA;
		DataBuff[1] = 0x02;
		UART_SendData(DataBuff,2);
	}
	else if(*EventType == EVENT_RECV_DATA) {
		DataBuff[0] = 0xAA;
		DataBuff[1] = 0x03;
		UART_SendData(DataBuff,2);
	}
}


void printf(u8_t *string_ptr,u16_t len)
{
	u8_t buff[100];
	xmemcpy(buff,string_ptr,len);
	UART_SendData(buff,len);
}
#endif


